﻿using IotClientApp.Server.Devices;
using IotClientApp.Server.Entity;
using IotClientApp.Server.Services;
using IotClientApp.Shared;
using IotClientApp.Shared.Enums;
using IotModel;
using IotUtil;
using Microsoft.AspNetCore.Mvc;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.SS.Util;
using PluginInterface;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics.CodeAnalysis;
using System.Text;

namespace IotClientApp.Server.Controllers
{
    [ApiController]
    [Route("api/[controller]/[action]")]
    public class ParamController : ControllerBase
    {
        private readonly IParamService _paramService;
        private readonly ILogger<ParamController> _logger;
        public ParamController(IParamService paramService, ILogger<ParamController> logger)
        {
            _paramService = paramService;
            _logger = logger;
        }

        /// <summary>
        /// 获取参数
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageResponse<RealDataModel>> GetRealData(GetRealDataModel input)
        {
            var items = await _paramService.GetRealData(input);
            return items;
        }
        /// <summary>
        /// 获取设备参数
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<PageResponse<DeviceParamModel>> GetDeviceParams(GetDeviceParamModel input)
        {
            var items = await _paramService.GetDeviceParams(input);
            return items;
        }
        /// <summary>
        /// 参数编辑
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ApiResult<SavePointInfoModel>> SavePointInfo(SavePointInfoModel input)
        {
            var items = await _paramService.SavePointInfo(input);
            return items;
        }
        [HttpPost]
        public async Task<ApiResult<string>> UploadFile([FromForm] IEnumerable<IFormFile> files, [FromQuery] string deviceId)
        {
            var result = new ApiResult<string>();
            if (files != null && files.Count() > 0)
            {
                var table = await ExcelHelper.ExcelToDataTable(files.First());
                var inputs = new List<SavePointInfoModel>();
                foreach (DataRow row in table.Rows)
                {
                    var name = row["名称"];
                    var addr = row["地址"];
                    var dataType = row["类型"];
                    var endianType = row["大小端"];
                    var expressions = row["表达式"];
                    var readWrite = row["读写"];
                    var desc = row["描述"];
                    if (name == null || string.IsNullOrWhiteSpace(name.ToString())
                        || addr == null || string.IsNullOrWhiteSpace(addr.ToString())
                        || dataType == null || string.IsNullOrWhiteSpace(dataType.ToString())
                        || endianType == null || string.IsNullOrWhiteSpace(endianType.ToString())
                        || readWrite == null || string.IsNullOrWhiteSpace(readWrite.ToString()))
                    {
                        result.Code = ResultCode.BadRequest;
                        return result;
                    }
                    SavePointInfoModel pointInfo = new SavePointInfoModel
                    {
                        Name = name.ToString(),
                        Address = int.Parse(addr.ToString())
                    };
                    switch (endianType.ToString())
                    {
                        case "大端":
                            pointInfo.EndianType = (short)EndianEnum.BigEndian;
                            break;
                        case "小端":
                            pointInfo.EndianType = (short)EndianEnum.LittleEndian;
                            break;
                        case "大端交换":
                            pointInfo.EndianType = (short)EndianEnum.BigEndianSwap;
                            break;
                        case "小端交换":
                            pointInfo.EndianType = (short)EndianEnum.LittleEndianSwap;
                            break;
                    }
                    if (expressions != null)
                    {
                        pointInfo.Expressions = expressions.ToString();
                    }
                    if (desc != null)
                    {
                        pointInfo.Desc = desc.ToString();
                    }
                    pointInfo.ReadWrite = "Read";
                    switch (readWrite.ToString())
                    {
                        case "读":
                            pointInfo.ReadWrite = "Read";
                            break;
                        case "读写":
                            pointInfo.ReadWrite = "ReadWrite";
                            break;
                    }
                    switch (dataType.ToString().ToLower())
                    {
                        case "int16":
                            pointInfo.DataType = (short)DataTypeEnum.Int16;
                            break;
                        case "int32":
                            pointInfo.DataType = (short)DataTypeEnum.Int32;
                            break;
                        case "float":
                            pointInfo.DataType = (short)DataTypeEnum.Float;
                            break;
                        case "double":
                            pointInfo.DataType = (short)DataTypeEnum.Double;
                            break;
                        case "bit":
                            pointInfo.DataType = (short)DataTypeEnum.Bit;
                            break;
                        default:
                            {
                                result.Code = ResultCode.BadRequest;
                                result.ErrorMsg = $"{dataType}错误！";
                                return result;
                            }
                    }
                    inputs.Add(pointInfo);
                }
                if (inputs.Count() > 0)
                {
                    result = await _paramService.SavePointInfos(inputs, deviceId);
                }
            }
            return result;
        }
        [HttpPost]
        public async Task<IActionResult> DownloadIoTDevicePhyList(GetDeviceParamModel input)
        {
            ApiResult<string> result = new ApiResult<string> { };
            input.PageIndex = 0;
            input.PageSize = 0;
            var apidata = await _paramService.GetDeviceParams(input);
            var tmpPath = System.IO.Path.Combine(Directory.GetCurrentDirectory(), "Template", "Param");
            try
            {
                var eqtypestdata = apidata.Data;
                string fileName = string.Empty;
                //模板数据从第五行开始，共11列
                fileName = System.IO.Path.Combine(tmpPath, "Points.xls");

                //操作excel模板，填充数据
                FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                HSSFWorkbook hssfworkbook = new HSSFWorkbook(fileStream);
                var sheet0 = hssfworkbook.GetSheetAt(0);
                var rowindex = 1;
                var clomuindex = 13;
                #region 单元格下拉框设置
                var dataTypes = new List<string> { "Int16", "Int32", "Float", "Double" };
                var endianTypes = new List<string> { "无", "大端", "小端", "大端交换", "小端交换" };
                var readWriteTypes = new List<string> { "可读", "可读可写" };
                //创建数据源sheet
                //数据类型
                string sheetName = "Type";
                ISheet typeSheet = hssfworkbook.CreateSheet(sheetName);
                hssfworkbook.SetSheetHidden(hssfworkbook.GetSheetIndex(typeSheet), true);
                int rowNo = 0;
                foreach (var item in dataTypes)
                {
                    typeSheet.CreateRow(rowNo++).CreateCell(0).SetCellValue(item);
                }
                var rangeName = sheetName + "Range";
                IName range = hssfworkbook.CreateName();
                range.RefersToFormula = sheetName + "!$A$1:$A$" + rowNo;
                range.NameName = rangeName;
                CellRangeAddressList regions = new CellRangeAddressList(1, 65535, 2, 2);

                DVConstraint constraint = DVConstraint.CreateFormulaListConstraint(rangeName);
                HSSFDataValidation dataValidate = new HSSFDataValidation(regions, constraint);
                dataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。");
                dataValidate.ShowPromptBox = true;
                sheet0.AddValidationData(dataValidate);
                //大小端
                string bssheetName = "BigSamll";
                ISheet bsSheet = hssfworkbook.CreateSheet(bssheetName);
                hssfworkbook.SetSheetHidden(hssfworkbook.GetSheetIndex(bsSheet), true);
                int bsrowNo = 0;
                foreach (var item in endianTypes)
                {
                    bsSheet.CreateRow(bsrowNo++).CreateCell(0).SetCellValue(item);
                }
                var bsrangeName = bssheetName + "Range";
                IName bsrange = hssfworkbook.CreateName();
                bsrange.RefersToFormula = bssheetName + "!$A$1:$A$" + bsrowNo;
                bsrange.NameName = bsrangeName;
                CellRangeAddressList bsregions = new CellRangeAddressList(1, 65535, 3, 3);


                DVConstraint bsconstraint = DVConstraint.CreateFormulaListConstraint(bsrangeName);
                HSSFDataValidation bsdataValidate = new HSSFDataValidation(bsregions, bsconstraint);
                bsdataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。");
                bsdataValidate.ShowPromptBox = true;
                sheet0.AddValidationData(bsdataValidate);


                //读写
                string rwsheetName = "ReadWrite";
                ISheet rwSheet = hssfworkbook.CreateSheet(rwsheetName);
                hssfworkbook.SetSheetHidden(hssfworkbook.GetSheetIndex(rwSheet), true);
                int rwrowNo = 0;
                foreach (var readWriteType in readWriteTypes)
                {
                    rwSheet.CreateRow(rwrowNo++).CreateCell(0).SetCellValue(readWriteType);
                }
                var rwrangeName = rwsheetName + "Range";
                IName rwrange = hssfworkbook.CreateName();
                rwrange.RefersToFormula = rwsheetName + "!$A$1:$A$" + rwrowNo;
                rwrange.NameName = rwrangeName;
                CellRangeAddressList rwregions = new CellRangeAddressList(1, 65535, 3, 3);


                DVConstraint rwconstraint = DVConstraint.CreateFormulaListConstraint(rwrangeName);
                HSSFDataValidation rwdataValidate = new HSSFDataValidation(rwregions, rwconstraint);
                rwdataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。");
                rwdataValidate.ShowPromptBox = true;
                sheet0.AddValidationData(rwdataValidate);


                #endregion
                //处理行数据
                var resultItems = apidata.Data;
                for (int j = 0; j < resultItems.Count; j++)
                {
                    //处理列数据
                    var itemRow = resultItems[j];
                    var rowCell = sheet0.GetRow(rowindex);//获得第二行
                    if (rowCell == null)
                    {
                        rowCell = sheet0.CreateRow(rowindex);
                        for (int i = 0; i < clomuindex; i++)
                        {
                            rowCell.CreateCell(i);
                        }
                    }
                    try
                    {
                        rowCell.GetCell(0).SetCellValue(itemRow.Name);//第二行第一列  
                        rowCell.GetCell(1).SetCellValue(itemRow.Address);//第二行第二列     
                        rowCell.GetCell(2).SetCellValue(itemRow.DataTypeName);//第二行第三列
                        rowCell.GetCell(3).SetCellValue(itemRow.EndianTypeName);//第二行第四列
                        rowCell.GetCell(4).SetCellValue(itemRow.ReadWriteName);
                        rowCell.GetCell(5).SetCellValue(itemRow.Expressions);//参数含义                                             //参数含义
                        rowCell.GetCell(6).SetCellValue(itemRow.Desc);//第二行第四列
                        rowindex++;
                    }
                    catch (Exception ex)
                    {
                        var a = rowindex;
                        var b = itemRow;
                        var c = rowCell;
                        throw ex;
                    }
                }
                MemoryStream memoryStream = new MemoryStream();
                hssfworkbook.Write(memoryStream);
                memoryStream.Flush();
                memoryStream.Position = 0;
                hssfworkbook.Close();
                return File(memoryStream.ToArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "参数.xls");
            }
            catch (Exception ex)
            {
                _logger.LogError(string.Format("{0}方法被调用，发生了错误:{1}", this.GetType().FullName, ex.Message.ToString()));
                result.Code = ResultCode.Fail;
                result.ErrorMsg = ex.Message;
            }
            return StatusCode(500, result);
        }
    }
}